使用vue 您所在的位置:网站首页 vue admin template简介 使用vue

使用vue

2024-06-28 19:24| 来源: 网络整理| 查看: 265

使用vue-admin-template搭建简单增删改查导入导出项目及CentOs服务器部署 原创

充电鸭鸭 2023-05-10 22:40:13 博主文章分类:java ©著作权

文章标签 vue centos nginx java elementui 文章分类 Html/CSS 前端开发

©著作权归作者所有:来自51CTO博客作者充电鸭鸭的原创作品,请联系作者获取转载授权,否则将追究法律责任

1. Vue-admin-template1. 简介

vueAdmin-template是基于vue-element-admin的一套后台管理系统基础模板(最少精简版),可作为模板进行二次开发。

GitHub地址:https://github.com/PanJiaChen/vue-admin-template

根据用户角色来动态生成侧边栏的分支:https://github.com/PanJiaChen/vue-admin-template/tree/permission-control

2. 安装和运行# 首先使用git下载源码 git clone https://github.com/PanJiaChen/vue-admin-template.git # 将文件夹修改成我们自己的项目名称 如 vue-demo # 使用git窗口修改,强化linux命令 mv vue-admin-template vue-demo # 使用cmd或者IDE打开文件夹 如 vscode webstorm # 下载安装项目所需的依赖 此步需要有node npm install #运行 npm run dev #前端打包 npm run build:prod2. 前端相关配置1. 禁用EsLint

在 vue.config.js第30行禁用ESLint语法检查

lintOnSave: false,2. 修改页面标题

在 src/setting.js第三行处修改页面标题

module.exports = { title: 'vue测试系统', }3. 国际化设置

在 src/main.js 第7行处修改语言

import locale from 'element-ui/lib/locale/lang/zh-CN' //lang i18n4. 下拉菜单修改

使用vue-admin-template搭建简单增删改查导入导出项目及CentOs服务器部署_nginx

5. 登录页修改

在src/views/login/index.vue 修改登录页面标题和登录按钮等

3. 定义api

在src/api下创建文件夹report

1. 导出整个对象

此方法只导出一个default对象,使用的时候可以将一阵个文件导入成为一个对象来使用。

在report文件夹下创建reportApi.js

import request from '@/utils/request' export default { /** * 分页查询 * @param data 查询参数 * @returns {AxiosPromise} */ fetchReportList(data) { return request({ url: `/manager/report/page`, method: 'get', params: data }) }, /** * 根据id获取数据 * @param data 要查询的id * @returns {AxiosPromise} */ getReportById(data) { return request({ url: `/manager/report/${data}`, method: 'get' }) }, /** * 新增或更新方法, 后端判断,如果有id则更新没有id则创建, * 也可以直接使用MybatisPlus的saveOrUpdate方法简化操作 * @param data 表单数据 * @returns {AxiosPromise} */ saveOrUpdateReport(data) { return request({ url: '/manager/report/saveOrUpdate', method: 'post', data }) }, /** * 根据id删除数据,逻辑删除 * 实体类删除属性上添加 @TableLogic即可标记 使用MybatisPlus的removeById即可 * @param data * @returns {AxiosPromise} */ removeReportById(data) { return request({ url: `/manager/report/${data}`, method: 'delete' }) }, getReportErrorPage() { return request({ url: '/manager/report/errorPage', method: 'get' }) }, /** * 文件上传 批量 * @param url 要上传的文件地址 * @param file 文件数组 * @returns {AxiosPromise} */ upload(url, file) { // 创建 FormData对象 let data = new FormData() // 将文件放置到data里,files对应后端MultipartFile 的变量名 file.forEach(everyFile => { data.append("files", everyFile.raw) }) return request({ //这里可以直接写url, url: url, method: 'post', data }) } }

使用的时候直接导出整个对象

import reportApi from "@/api/report/reportApi"; export default { name: 'reportList', data(){ return{ } }, created() { }, methods:{ fetchList(data){ reportApi.fetchReportList(data) .then(resp => { }) } } } 2. 单独导出每个方法

在 src/api/report下创建report.js

import request from '@/utils/request' export function fetchReportList(data){ return request({ url: `/manager/report/page`, method: 'get', params:data }) } export function getReportById(data){ return request({ url: `/manager/report/${data}`, method:'get' }) } export function importExcel(data){ return request({ url: '/manager/report/importBatch', method:'post', data }) } export function export2Excel(data){ return request({ url: '/manager/report/export', method:'get' }) } export function saveOrUpdateReport(data){ return request({ url: '/manager/report/saveOrUpdate', method:'post', data }) } export function removeReportById(data){ return request({ url : `/manager/report/${data}`, method:'delete' }) } export function getReportErrorPage(){ return request({ url: '/manager/report/errorPage', method:'get' }) } export function upload(url,file){ let data = new FormData() file.forEach(everyFile => { data.append("files",everyFile.raw) }) return request({ url:url, method:'post', data }) }

使用的时候按需引入即可,不需要都引入

import {fetchReportList,removeReportById,upload} from '@/api/report/report' export default { name: 'reportList', data(){ return{ reportList:[], } }, created(){ this.fetchList(); }, methods:{ clearSearchForm(){ this.searchForm = {} this.fetchList() }, fetchList() { let data = { name:this.searchForm.name, phone:this.searchForm.phone, idCard:this.searchForm.idCard, testingResult:this.searchForm.testingResult, queryStartTime:this.searchForm.queryStartTime, queryEndTime:this.searchForm.queryEndTime, pageNum:this.pageNum, pageSize:this.pageSize } fetchReportList(data).then(resp => { this.reportList = resp.data.list this.total = resp.data.total this.pageSize = resp.data.pageSize this.pageNum = resp.data.pageNum }) } } 3. 总结

我自己是使用第二种方式的,可能也是受到了身边前端同时的影响,第一种可以有效的避免方法名重复我觉得哈哈哈🤤

4. 配置项目路由

在src/router/index.js中的constatnRoutes修改

{ path: '/report', component: Layout, redirect: '/report/list', name: 'report', meta:{title: '核酸检测管理',icon: 'el-icon-search'}, alwaysShow:true, children: [ { path: 'list', name: 'reportList', component: () => import('@/views/report/list'), meta: { title: '统计结果', icon: 'form' } }, { path: 'save', name: 'saveReport', component: () => import('@/views/report/form'), meta: { title: '添加核酸检测数据', icon: 'form' } }, { //相当于占位符,这个id可以用this.$route.params.id取出来 path: 'edit/:id', name: 'editReport', component: () => import('@/views/report/form'), meta: { title: '修改核酸检测结果', icon: 'form' }, hidden:true }, ] },

序号

属性

子属性

描述

1

path

路由的路径

2

name

路由的名称,不能重复

3

redirect

重定向的地址

4

component

引用的组件

5

meta

组件的描述

6

title

组件的标题

7

icon

组件的标签

8

alwaysShow

是否永远展示,

false时 有且仅有一个子组件时不展示

9

hidden

是否隐藏

10

children

子组件

抽离出来的数据库实体类

create teble sys_menu( id int primary key auto_increment comment '', parent_id int comment '', path varchar(50) not null unique comment '', name varchar(50) not null unique comment '', redirect varchar(100) comment '', component varchar(50) comment '', title varchar(50) comment '', icon varchar(50) comment '', always_show bit(1) comment '', hidden bit(1) comment '', create_by varchar(50) comment '', create_time datetime default now() comment '', update_by varchar(50) comment '', update_time datetime comment '', del_flag tinyint default 0 comment '0未删除 1已删除' )comment '系统菜单表';5. 创建组件(使用两个vue页面)

在src/views下创建文件夹report

1. 创建列表组件 list.vue1. 基础的表格展示

在report文件夹下创建list.vue,使用elementui的el-table组件,elementui提供了一个slot-scope可以用来将后端传过来的数据转换成我们自己想要的数据,scope.row就是用户当前在操作的那一行

身份证 护 照 其 他 阳性 阴性 暂无结果 import {fetchReportList} from '@/api/report/report' export default { data() { return { reportList: [] } } created() { this.fetchList() }, methods: { fetchList() { fetchReportList().then(resp => { this.reportList = resp.data }) } } } 2. 创建表单组件form.vue

在src/view/report下创建form.vue,此页面并没有添加表单校验,如有需要请参考表单验证。

为了更好的控制每行的展示,可以使用栅格组件中的el-row来实现。一行 24列, 在el-col中使用:span控制占用多少。

在生命周期created函数中,判断当前路由中的id是不是空值,这个值可以在ver devtools中查看到。如果存在id的话,则调用查询的接口,将获取到的数据展示在表单中

{{loadingText}} import {getReportById, saveOrUpdateReport} from "@/api/report/report"; export default { data(){ return{ loadingText:'保存', report:{ }, pickerOptions: { disabledDate(time) { return time.getTime() > Date.now(); }, shortcuts: [{ text: '今天', onClick(picker) { picker.$emit('pick', new Date()); } }, { text: '昨天', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24); picker.$emit('pick', date); } }, { text: '一周前', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); picker.$emit('pick', date); } }] } } }, created() { let id = this.$route.params.id if(id){ this.getById(id) } }, methods:{ getById(id){ getReportById(id).then(resp => { this.report = resp.data }) }, saveOrUpdate(){ saveOrUpdateReport(this.report).then(resp => { this.$message.success(resp.message) this.$router.push('/report/list') }) } } }

当然,也可以给最下方的保存按钮添加加载中这种特效

{{loadingText}} import {saveOrUpdateReport} from '@/api/report/report' export default { data() { return { loadingIcon: 'el-icon-success', loading: false, loadingText: '保存', form: {} } }, methods: { saveOrUpdate() { this.changeLoadBtn('el-icon-loading', true, '保存中...') saveOrUpdateReport(this.form).then(resp => { this.$message.success(resp.messge) //保存成功跳转到列表页面 this.$router.push('/report/list') }).catch(err => { this.changeLoadBtn('el-icon-error', false. '保存失败' ) }) }, //变更加载按钮 changeLoadBtn(loadingIcon, loading, loadingText) { this.loadingIcon = loadingIcon this.loading = loading this.loadingText = loadingText } } } 3. 列表页新增操作列

在el-table最后添加一列操作列,用来编辑和删除

修改 删除 import {removeReportById} from '@/api/report/report' export default { data() { return { form: {} } }, methods: { delReport(id) { removeReportById(id).then(resp => { this.$message.success(resp.message) }) } } }

因为编辑按钮点击之后就跳转了form.vue,所以直接使用router-link会比较方便,应该相当于下边这种写法,但是我没验证过。

修改 export default { data() { return { form: {} } }, methods: { editReport(id) { this.$router.push(`/report/edit/${id}`) } } } 4. 新增查询功能1. 修改页面组件

在页面的最上方添加查询字段,在需要输入框添加@keyup.enter.native 可以使回车键松开的时候调用查询方法,添加@blur是的输入框失去焦点的时候调用查询方法,下拉选择狂可以使用@change来调用

- 清空条件 查询 下载模板 导入 导出 错误数据 ... 2. 修改api

将searchForm里边所有的值都赋值给我们要查询的data

import {fetchReportList, getReportErrorPage, removeReportById,upload} from '@/api/report/report' export default { name: 'reportList', data(){ return{ reportList:[], searchForm:{ name:'', phone: '', idCard:'', testingResult:'', queryStartTime:'', queryEndTime:'' }, } }, methods:{ fetchList(){ let data = { name:this.searchForm.name, phone:this.searchForm.phone, idCard:this.searchForm.idCard, testingResult:this.searchForm.testingResult, queryStartTime:this.searchForm.queryStartTime, queryEndTime:this.searchForm.queryEndTime, } fetchReportList(data).then(resp => { this.reportList = resp.data.list }) } } }

当然这种方法不叫繁琐,也可以使用...来进行赋值

import {fetchReportList, getReportErrorPage, removeReportById,upload} from '@/api/report/report' export default { name: 'reportList', data(){ return{ reportList:[], searchForm:{ name:'', phone: '', idCard:'', testingResult:'', queryStartTime:'', queryEndTime:'' }, } }, methods:{ fetchList(){ // 可以将searchForm对象解构赋值,与上边的挨个赋值效果一致 let data = { ...this.searchForm } fetchReportList(data).then(resp => { this.reportList = resp.data.list }) } } } 5. 添加分页功能1. 修改页面

在el-table标签下添加分页组件el-pagination

... 2. 修改api

添加分页相关的方法和属性。

首先data中添加了三个属性total总条数,pageNum查询页数,pageSize每页展示多少条。

其次methods中需要添加pageSize和pageNum变化的方法。

在fetchList方法查询参数data中添加分页的参数pageNum和pageSize即可。

分页可以使用async,这一部分我还没研究到。🤡

import {fetchReportList} from '@/api/report/report' export default { name: 'reportList', data(){ return{ reportList:[], searchForm:{ name:'', phone: '', idCard:'', testingResult:'', queryStartTime:'', queryEndTime:'' }, total:0, pageSize:10, pageNum:1 } }, created(){ this.fetchList(); }, methods:{ clearSearchForm(){ this.searchForm = {} this.fetchList() }, fetchList() { let data = { ...this.searchForm, pageNum:this.pageNum, pageSize:this.pageSize } console.log(data,'data') fetchReportList(data).then(resp => { this.reportList = resp.data.list this.total = resp.data.total this.pageSize = resp.data.pageSize this.pageNum = resp.data.pageNum }) }, handleSizeChange(pageSize){ this.pageSize =pageSize this.fetchList(); }, handleCurrentChange(pageNum){ this.pageNum = pageNum this.fetchList(); } } } 6. 添加导入导出功能

在搜索的后边添加导入导出功能按钮

1. 修改页面

当然也可以将下载模板放置到弹出的el-dialog中

下载模板 导入 导出 将文件拖到此处,或点击上传 * 请选择 .xls 或 .xlsx后缀的文件 确认 取消 2. 修改api import {fetchReportList, getReportErrorPage, removeReportById,upload} from '@/api/report/report' export default { name: 'reportList', data(){ return{ reportList:[], searchForm:{ name:'', phone: '', idCard:'', testingResult:'', queryStartTime:'', queryEndTime:'' }, dialogVisible: false, //文件上传对话框是否显示 BASE_API: process.env.VUE_APP_BASE_API, //获取后端接口地址 total:0, pageSize:10, pageNum:1, /* 上传时附带的额外参数,返回是一个对象 */ extraParam: {}, /* 已上传的文件列表 */ fileList: [], /* 是否在选取文件后立即进行上传 */ autoUpload: false, fileSizeLimit:100, fileType:'.xls,.xlsx', uploadAction:'http://localhost:8090/manager/report/import' } }, created(){ this.fetchList(); }, methods:{ clearSearchForm(){ this.searchForm = {} this.fetchList() }, fetchList() { let data = { ...this.searchForm, pageNum:this.pageNum, pageSize:this.pageSize } console.log(data,'data') fetchReportList(data).then(resp => { this.reportList = resp.data.list this.total = resp.data.total this.pageSize = resp.data.pageSize this.pageNum = resp.data.pageNum }) }, handleSizeChange(pageSize){ this.pageSize =pageSize this.fetchList(); }, handleCurrentChange(pageNum){ this.pageNum = pageNum this.fetchList(); }, export2Excel(){ window.location.href =this.BASE_API + `/manager/report/export?name=${this.searchForm.name}&phone=${this.searchForm.phone}&idCard=${this.searchForm.idCard}&testingResult=${this.searchForm.testingResult}` }, /* 文件列表移除文件成功时的钩子 */ handleRemove(file, fileList) { return this.$message.success(`已成功移除"${file.name}"文件`) }, /* 处理上传失败时的勾子 */ handleUploadError(err, file, fileList) { this.$message.error(`文件上传失败`) }, /* 文件删除前的勾子 */ beforeRemove(file, fileList) { return this.$confirm(`确定移除"${file.name}"文件吗?`) }, /* 上传文件之前的钩子 因设置了auto-upload为false,如果使用before-upload,虽有提示,但是还是会请求服务器*/ beforeUpload(file,fileList) { // 1、判断文件名是否重复,不允许上传相同文件 let existFile = fileList.slice(0, fileList.length - 1).find(f => f.name === file.name) if(existFile){ fileList.pop() this.$message.error(file.name+" 文件已存在!") } // 2、获取文件后缀 fileList.forEach(everyFile => { const fileType = everyFile.name.substring(everyFile.name.lastIndexOf('.')) if(this.fileType.search(fileType) === -1){ fileList.pop() this.$message.error("上传文件的类型不正确"+"文件类型必须为" + this.fileType + '') } }) this.fileList = fileList; }, /* 文件超出个数限制时的钩子 */ handleExceed(files, fileList) { this.$message.error(`当前限制选择`+ this.fileSizeLimit +`个文件,本次选择了 ${files.length} 个文件,已超出了文件最大上传个数`) }, /* 文件上传成功时的钩子 */ handleUploadSuccess(res, file, fileList) { console.info(JSON.stringify(res)) }, /* 确定上传 */ submitUpload() { upload(this.uploadAction,this.fileList).then(res => { this.$message.success(res.message) this.fileList = [] this.dialogVisible = false }); }, downloadTemplate(){ window.location.href = this.BASE_API + '/manager/report/downloadTemplate' } } } 7. 最终的list.vue - 清空条件 查询 下载模板 导入 导出 错误数据 身份证 护 照 其 他 阳性 阴性 暂无结果 修改 删除 将文件拖到此处,或点击上传 * 请选择 .xls 或 .xlsx后缀的文件 确认 取消 import {fetchReportList, getReportErrorPage, removeReportById,upload} from '@/api/report/report' export default { name: 'reportList', data(){ return{ reportList:[], searchForm:{ name:'', phone: '', idCard:'', testingResult:'', queryStartTime:'', queryEndTime:'' }, dialogVisible: false, //文件上传对话框是否显示 BASE_API: process.env.VUE_APP_BASE_API, //获取后端接口地址 total:0, pageSize:10, pageNum:1, /* 上传时附带的额外参数,返回是一个对象 */ extraParam: {}, /* 已上传的文件列表 */ fileList: [], /* 是否在选取文件后立即进行上传 */ autoUpload: false, fileSizeLimit:100, fileType:'.xls,.xlsx', uploadAction:'http://localhost:8090/manager/report/import' } }, created(){ this.fetchList(); }, methods:{ clearSearchForm(){ this.searchForm = {} this.fetchList() }, fetchList() { let data = { ...this.searchForm, pageNum:this.pageNum, pageSize:this.pageSize } console.log(data,'data') fetchReportList(data).then(resp => { this.reportList = resp.data.list this.total = resp.data.total this.pageSize = resp.data.pageSize this.pageNum = resp.data.pageNum }) }, delReport(id){ this.$confirm('此操作将永久删除该记录,是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { removeReportById(id).then(resp => { this.$message.success(resp.message) this.fetchList() }) }).catch(err => { this.$message({ type: 'info', message: '已取消删除' }) }) }, handleSizeChange(pageSize){ this.pageSize =pageSize this.fetchList(); }, handleCurrentChange(pageNum){ this.pageNum = pageNum this.fetchList(); }, export2Excel(){ window.location.href =this.BASE_API + `/manager/report/export?name=${this.searchForm.name}&phone=${this.searchForm.phone}&idCard=${this.searchForm.idCard}&testingResult=${this.searchForm.testingResult}` }, getErrorPage(){ getReportErrorPage().then(resp => { this.reportList = resp.data.list this.total = resp.data.total this.pageSize = resp.data.pageSize this.pageNum = resp.data.pageNum }) }, /* 文件列表移除文件成功时的钩子 */ handleRemove(file, fileList) { return this.$message.success(`已成功移除"${file.name}"文件`) }, /* 处理上传失败时的勾子 */ handleUploadError(err, file, fileList) { this.$message.error(`文件上传失败`) }, /* 文件删除前的勾子 */ beforeRemove(file, fileList) { return this.$confirm(`确定移除"${file.name}"文件吗?`) }, /* 上传文件之前的钩子 因设置了auto-upload为false,如果使用before-upload,虽有提示,但是还是会请求服务器*/ beforeUpload(file,fileList) { // 1、判断文件名是否重复,不允许上传相同文件 let existFile = fileList.slice(0, fileList.length - 1).find(f => f.name === file.name) if(existFile){ fileList.pop() this.$message.error(file.name+" 文件已存在!") } // 2、获取文件后缀 fileList.forEach(everyFile => { const fileType = everyFile.name.substring(everyFile.name.lastIndexOf('.')) if(this.fileType.search(fileType) === -1){ fileList.pop() this.$message.error("上传文件的类型不正确"+"文件类型必须为" + this.fileType + '') } }) this.fileList = fileList; }, /* 文件超出个数限制时的钩子 */ handleExceed(files, fileList) { this.$message.error(`当前限制选择`+ this.fileSizeLimit +`个文件,本次选择了 ${files.length} 个文件,已超出了文件最大上传个数`) }, /* 文件上传成功时的钩子 */ handleUploadSuccess(res, file, fileList) { console.info(JSON.stringify(res)) }, /* 确定上传 */ submitUpload() { upload(this.uploadAction,this.fileList).then(res => { this.$message.success(res.message) this.fileList = [] this.dialogVisible = false }); }, downloadTemplate(){ window.location.href = this.BASE_API + '/manager/report/downloadTemplate' } } } 6. 创建组件(使用dialog弹出新增编辑页面)

暂时没时间写

7. 后端创建

创建出来后端项目,配置好跨域,添加context-path

server: port: 8090 servlet: context-path: /manager8. 运行前配置

前后端分离的配置一般都是通过Nginx来管理静态资源,在通过Nginx将请求代理到后台的,所以需要对前端项目进行相关的配置

1. 本地运行1. 修改 .env.development文件

将VUE_APP_BASE_API修改为Nginx运行端口

VUE_APP_BASE_API = 'http://localhost'2. 修改 request.js

将src/utils/request.js中的axios相关哦诶之修改一下

修改baseURLconst service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout:5000 })修改响应拦截器service.interceptors.response.use(response =>{ const res = response.data // 这里添加上自己后端返回正确的编码 if (res.code !== 20000 && res.code != 200) {} })3. 修改mock服务

本次未整合后端的登录注册服务,依旧使用原来的mock

修改mock/mock-server.js第39行url: new RegExp(`/dev-api${url}`),修改src/api/user.js为每一个接口添加baseURL import request from '@/utils/request' export function login(data) { return request({ baseURL: '/dev-api', url: '/vue-admin-template/user/login', method: 'post', data }) } export function getInfo(token) { return request({ baseURL: '/dev-api', url: '/vue-admin-template/user/info', method: 'get', params: { token } }) } export function logout() { return request({ baseURL: '/dev-api', url: '/vue-admin-template/user/logout', method: 'post' }) }4. Nginx修改

前端打包

npm run bubild:prod

将前端打包后生成的dist文件夹复制到Nginx解压目录下,修改conf/nginx.conf

server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root dist; index index.html index.htm; } location /manager/ { proxy_pass http://localhost:8090; } }

在nginx解压目录的文件地址栏输入cmd,在cmd窗口运行Nginx

start nginx.exe

启动后端项目,并使用浏览器打开localhost进行测试

2. 部署线上环境1. 后端修改

在pom.xml添加打包的相关配置,在IDEA右侧maven -->LifeCycle --> package 或者直接执行mvn clean package

org.springframework.boot spring-boot-maven-plugin net.lesscoding.MainApp 1.4.2.RELEASE org.springframework.boot spring-boot-maven-plugin build-info org.sonarsource.scanner.maven sonar-maven-plugin 3.2 2. 服务器相关配置Centos中Java初始化环境搭建nginx安装、前后端分离部署流程Centos 安装Nginx错误集锦nginx安装部署ssl证书

收藏 评论 分享 举报

上一篇:JSP九大内置对象及其使用教程

下一篇:杂七杂八的知识



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有